pull: Close another race
authorColin Walters <walters@verbum.org>
Mon, 20 Jan 2014 11:17:45 +0000 (06:17 -0500)
committerColin Walters <walters@verbum.org>
Mon, 20 Jan 2014 11:26:49 +0000 (06:26 -0500)
Only send _IDLE messages if and only if we state transition the main
thread (from idle -> !idle or !idle -> idle).  This ensures that we
don't send IDLE, then get it back, and process that when we're !idle.

src/libostree/ostree-repo-pull.c

index cfbe81a51ddedad8cc4571f712c234e183113fc6..c95fb41549dcae1ebae7a92c7b98b2dc66b1b9ac 100644 (file)
@@ -104,6 +104,7 @@ typedef struct {
   GHashTable       *requested_content; /* Maps object name to itself */
   guint             checking_metadata_scan_complete : 1;
   guint             metadata_scan_complete : 1;
+  gboolean          was_idle;
   guint             idle_serial;
   guint             n_outstanding_metadata_fetches;
   guint             n_outstanding_metadata_write_requests;
@@ -253,24 +254,6 @@ throw_async_error (OtPullData          *pull_data,
     }
 }
 
-static gboolean
-termination_condition (OtPullData           *pull_data,
-                       gboolean              current_fetch_idle,
-                       gboolean              current_write_idle)
-{
-  /* This is true in the phase when we're fetching refs */
-  if (pull_data->metadata_objects_to_scan == NULL)
-    {
-      if (!pull_data->fetching_sync_uri)
-        return TRUE;
-    }
-  else if (pull_data->metadata_scan_complete && current_fetch_idle && current_write_idle)
-    {
-      return TRUE;
-    }
-  return FALSE;
-}
-
 static void
 check_outstanding_requests_handle_error (OtPullData          *pull_data,
                                          GError              *error)
@@ -279,24 +262,37 @@ check_outstanding_requests_handle_error (OtPullData          *pull_data,
                                  pull_data->n_outstanding_content_fetches == 0);
   gboolean current_write_idle = (pull_data->n_outstanding_metadata_write_requests == 0 &&
                                  pull_data->n_outstanding_content_write_requests == 0);
+  gboolean current_idle = current_fetch_idle && current_write_idle;
 
   g_debug ("pull: scanning: %u fetching: %u staging: %u",
            !pull_data->metadata_scan_complete, !current_fetch_idle, !current_write_idle);
 
   throw_async_error (pull_data, error);
 
-  if (pull_data->metadata_objects_to_scan &&
-      !pull_data->checking_metadata_scan_complete &&
-      !pull_data->metadata_scan_complete &&
-      (current_fetch_idle && current_write_idle))
+  /* This is true in the phase when we're fetching refs */
+  if (pull_data->metadata_objects_to_scan == NULL)
+    {
+      if (!pull_data->fetching_sync_uri)
+        g_main_loop_quit (pull_data->loop);
+      return;
+    }
+
+  if (pull_data->was_idle && !current_idle)
     {
-      pull_data->checking_metadata_scan_complete = TRUE;
+      /* We transitioned to !idle */
+      g_debug ("pull: No longer idle");
       pull_data->idle_serial++;
+      pull_data->was_idle = FALSE;
+    }
+  else if (!pull_data->was_idle && current_idle)
+    {
+      pull_data->was_idle = TRUE;
       g_debug ("Sending new MSG_IDLE with serial %u", pull_data->idle_serial);
       ot_waitable_queue_push (pull_data->metadata_objects_to_scan,
                               pull_worker_message_new (PULL_MSG_IDLE, GUINT_TO_POINTER (pull_data->idle_serial)));
     }
-  else if (termination_condition (pull_data, current_fetch_idle, current_write_idle))
+
+  if (pull_data->metadata_scan_complete && current_idle)
     g_main_loop_quit (pull_data->loop);
 }